<template>
  <div style="width: 100%">
    <span v-if="props.showText">{{ currName }}</span>
    <el-select
      v-else
      ref="selectRef"
      v-model="currValue"
      class="cc-dict-selects"
      :filterable="props.filterable"
      :placeholder="calcPlaceholder"
      @change="handleChange"
      clearable
    >
      <el-option v-for="item in options"
        :key="item.key"
        :value="item.key"
        :label="item.value"
        :disabled="item.disabled === true"
      />
    </el-select>
  </div>
</template>

<script setup>
import { ref, watch, computed, inject, onMounted, onUnmounted } from 'vue';
import { getDictionary } from '@/utils/system';
import { useDisabled } from 'element-plus';
import emitter from "@/utils/bus";
import tool from "@/utils/tool";

const emit = defineEmits(['change']);
const props = defineProps({
  prop: {
    type: String,
    default: ''
  },
  dictCode: String,
  queryList: Object,
  filterable: {
    type: Boolean,
    default: true,
  },
  placeholder: {
    type: String,
    default: '--请选择--'
  },
  showText: Boolean
})

const formData = inject('formData');
const currValue = ref([]);
const currName = ref('');
const selectRef = ref();
const loading = ref(true);
const allOptions = ref([]);
const options = ref([]);
const inputDisabled = useDisabled();

const init = () => {
  loadDicAndShow(props.dictCode);
};

const handleChange = () => {
  formData[props.prop] = currValue.value.join(',');
  emit('change');
};

const loadDicAndShow = async(dictCode) => {
  if ((dictCode || '') === '') {
    allOptions.value = [];
    options.value = [];
  } else {
    loading.value = true;
    allOptions.value = await getDictionary(dictCode);
    loading.value = false;
    initCurrValue();
  }
  calcValue();
};

const filter = (list, queryList) => {
  if (!list || list.length === 0 || !queryList || queryList.length === 0) return list || [];
  return list.filter(item => queryList.every(query => {
    if (query.filterValue) {
      return item[query.filterFieldId] === query.filterValue;
    } else {
      return item[query.filterFieldId] === formData.value[query.dataFieldName];
    }
  }));
};

const calcValue = () => {
  if (props.showText) {
    let names = [];
    options.value.forEach(option => {
      currValue.value.forEach(value => {
        if (option.key === value) {
          names.push(option.value);
        }
      });
    });
    currName.value = names.join(',');
  }
};

const calcPlaceholder = computed(() => {
  return inputDisabled.value === true ? '' : props.placeholder;
});

const initCurrValue = () => {
  options.value = filter(allOptions.value, props.queryList);
  currValue.value = formData.value[props.prop] ? (formData.value[props.prop] || '').split(',') : [];
  if (!loading.value) {
    for (let value of currValue.value) {
      if (!options.value.find(item => item.key === value)) {
        currValue.value = [];
        return;
      }
    }
  }
};

watch(() => tool.deepClone(formData.value), () => {
  initCurrValue();
}, {immediate: true});

watch(() => props.dictCode, () => {
  init();
}, {immediate: true});

onMounted(() => {
  emitter.off("dictionary.change", init);
  emitter.on("dictionary.change", init);
});

onUnmounted(() => {
  emitter.off("dictionary.change", init);
});
</script>

<style scoped>
.cc-dict-selects {
  width: 100%;
}
</style>